class BasePlayer(object):
    def __str__(self):
        try:
            return self.name
        except AttributeError:
            # Fall back on Python default
            return super(BasePlayer, self).__repr__()

    def hunt_choices(*args, **kwargs):
        raise NotImplementedError("You must define a strategy!")

    def hunt_outcomes(*args, **kwargs):
        pass

    def round_end(*args, **kwargs):
        pass
class Player(BasePlayer):
    ''' 
        This is where documentation begins.
        In reality, I have another program that is FAR more intelligent than this one. The other algorithm can thus far accurately track players throughout the game. However, there are still some complex methods to be implemented (such as pattern analysis on moves done by players), and those might take more time than the deadline (considering I only was able to start coding this week). As a result, this "dumbed down" version is being used. (This is an explanation for why the name of this file is out_of_time_Player.py)

        The goal of this algorithm is to survive, not to win. This means that it simply tries to prolong its own survival, regardless of how much it is prolonging other's survival. The program has a top_level function, hunt_decisions, that runs certain scenarios for a given round number.

            In round 1, the program simply checks if m is reachable by itself. If so, it does the required hunts to get m. If not, the program plays all slacks.
            In round 2 and above, the program checks how many hunts the outer population is expected to get this round, and checks against a previous record how probable its estimate is. Based on these two facts, it determines how many, if any should be done, hunts the algorithm should do to reach m with minimal damage to the food amount. If hunts should not be done, it hunts with reputations higher than 0.5 .
    '''
    def __init__(self):
        self.name="Tanishq Aggarwal 2"
    def hunt_choices(self, round_number, current_food, current_reputation, m, player_reputations):
        self.round_number = round_number
        self.current_player_reputation = player_reputations
        if round_number == 1:
            if m <= len(player_reputations):
                player_reputations.sort()
                shortened_reps = player_reputations[m - 1:]
                hunt_decisions = ['s']*len(self.current_player_reputation)
                for i in shortened_reps:
                    indices = count(i, self.current_player_reputation)
                    for q in indices:
                        hunt_decisions[q] = 'h'
                return hunt_decisions
                self.m_projected_success = ['achievable']
            else:
                self.m_projected_success = ['not_achievable']
                return ['s']*len(player_reputations)
        else:
            if m <= len(player_reputations):
                expected_hunting_value = 0
                for reputations in player_reputations:
                    expected_hunting_value += (reputations * len(player_reputations))
                print expected_hunting_value
                probable_expected_hunting_value = expected_hunting_value * (self.m_hunting_successful_record.count('success')/len(self.m_hunting_successful_record))
                amount_of_hunting_self_has_to_do = m - probable_expected_hunting_value
                if amount_of_hunting_self_has_to_do <= 0:
                    self.m_projected_success += ['achievable']
                    return ['s']*len(player_reputations)
                elif 0 < amount_of_hunting_self_has_to_do <= len(player_reputations):
                    self.m_projected_success += ['achievable']
                    def count(x, lst):
                        ind = []
                        for i in lst:
                            if i == x:
                                ind.append(lst.index(x))
                        return ind
                    player_reputations.sort()
                    print int(amount_of_hunting_self_has_to_do)
                    shortened_reps = player_reputations[int(amount_of_hunting_self_has_to_do) - 1:]
                    hunt_decisions = ['s']*len(self.current_player_reputation)
                    for i in shortened_reps:
                        indices = count(i, self.current_player_reputation)
                        for q in indices:
                            hunt_decisions[q] = 'h'
                    return hunt_decisions
                else:
                    self.m_projected_success += ['not_achievable']
                    return ['s']*len(player_reputations)
            else:
                return ['h' if 0.5 <= rep <= 1 else 's' for rep in player_reputations]
    
    def round_end(self, award, m, number_hunters):
        if self.round_number == 1:
            if award > 0:
                if self.m_projected_success[-1] == 'achievable':
                    self.m_hunting_successful_record = ['success']
                elif self.m_projected_success[-1] == 'not_achievable':
                    self.m_hunting_successful_record = ['failure']
            else:
                if self.m_projected_success[-1] == 'not_achievable':
                    self.m_hunting_successful_record = ['success']
                elif self.m_projected_success[-1] == 'achievable':
                    self.m_hunting_successful_record = ['failure']        
        else:
            if award > 0:
                if self.m_projected_success[-1] == 'achievable':
                    self.m_hunting_successful_record.append('success')
                elif self.m_projected_success[-1] == 'not_achievable':
                    self.m_hunting_successful_record.append('failure')
            else:
                if self.m_projected_success[-1] == 'not_achievable':
                    self.m_hunting_successful_record.append('success')
                elif self.m_projected_success[-1] == 'achievable':
                    self.m_hunting_successful_record.append('failure')
    def hunt_outcomes(self, food_earnings): #Nothing to do here
        pass
    def count(x, list):
        ind = []
        for i in lst:
            if i == x:
                ind.append(lst.index(x))
        return ind